import sys
from pathlib import Path
current_file_path = Path(__file__)
project_root = current_file_path.parent.parent.parent
sys.path.append(str(project_root))

import simpy
import logging

from model import (
    Node,
    SimpleClock, 
    SimplePhy,
    Topology,
    TopologyChannel
)

logger = logging.getLogger('Test')

CLOCK_FREQ_HZ = 1000
CLOCK_SKEW_PPM = 10
SLOT_LENGTH = 10
FRAME_LENGTH = 10
SIM_CLOCKS = 5000

class TestMac():

    def __init__(self, env, node, phy):
        self.env = env
        self.node = node
        self.phy = phy
        
    def start(self):
        self.env.process(self.phy.start(self.node))
        self.env.process(self.timeslot_event())
        self.env.process(self.receive_event())
        self.env.process(self.main_loop())

    def main_loop(self):
        while True:
            yield self.env.timeout(1)
            logger.debug('main loop')
            if self.node.id == 1:
                self.phy.tx(self.node, {'id':1})

    def timeslot_event(self):
        while True:
            yield self.phy.wait_timeslot()
            f, s = self.phy.fs()
            #logger.debug(f'{f} {s}')

    def receive_event(self):
        while True:
            yield self.phy.wait_receive()
            logger.info(f'{self.node.id} rx')

def set_logger_level(name, level):
    logger = logging.getLogger(name)
    logger.setLevel(level)

def setup_logging():
    logging.basicConfig(
        level=logging.WARNING,
        format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    )
    set_logger_level('Clock', logging.DEBUG)
    set_logger_level('Phy', logging.INFO)
    set_logger_level('Test', logging.DEBUG)
    set_logger_level('TopologyChannel', logging.DEBUG)

if __name__ == '__main__':

    setup_logging()

    env = simpy.Environment()
    
    nodes = [Node(env, i) for i in range(2)]
    
    top = Topology(nodes)
    top.full_distribute()
    logger.info(top)
    
    channel = TopologyChannel(env, top, 0, 0)
    
    for n in nodes:
        clock = SimpleClock(env, CLOCK_FREQ_HZ, CLOCK_SKEW_PPM)
        phy = SimplePhy(env, clock, 1, 1, SLOT_LENGTH, FRAME_LENGTH)
        phy.set_channel(channel)
        mac = TestMac(env, n, phy)
        mac.start()

    # 运行仿真
    sim_duration = SIM_CLOCKS / CLOCK_FREQ_HZ
    print(f"Starting YansClock test simulation...")
    env.run(sim_duration)
    print("Simulation finished.")